<?php
/**
 * 框架 - 消息调度器类
 * 
 * @version $Id: Dispatcher.php 187 2011-05-23 07:57:55Z linsir123 $
 */
class Dispatcher
{
	/**
	 * @var 控制器目录
	 */
	public $controllerDir;
	
	/**
	 * @var 控制器类名称
	 */
	public $controllerName;
	
	/**
	 * @var 控制器类
	 */
	public $controllerClass;
	
	/**
	 * @var 控制器方法名称
	 */
	public $actionName;
	
	/**
	 * @var 异常信息
	 */
	public $exception;
	
	/**
	 * @var 是否系统404
	 */
	public $system404 = false;
	
	/**
	 * 构造函数
	 * 
	 * 从请求对象中取得请求数据数组
	 * 1、设置控制器所在目录
	 * 2、设置控制器和方法名称
	 * 3、并将其它参数设置到$_GET
	 */
	public function __construct()
	{
		$subApp = App::instance()->subApp;
		$this->controllerDir = APP_DIR.'Controller'.DS.(empty($subApp) ? '' : $subApp.DS);
		
		///
		$parts = App::getRequest()->getParts();
		if (is_array($parts) && $parts) {
			$this->controllerName = isset($parts[0]) ? trim($parts[0]) : '';
			$this->actionName = isset($parts[1]) ? trim($parts[1]) : '';
			
			///
			$count = count($parts);
			for ($i=2; $i<$count; $i+=2) 
				$_GET[$parts[$i]] = $parts[$i + 1];
		}
	}
	
	/**
	 * 在自定义的404处理器不存在情况下直接抛出系统异常
	 */
	public function goto404($exception = null)
	{
		lpSystem::h404();
		
		///
		$this->system404 or $this->exception = $exception;
		$controllerMiss = App::instance()->controllerMiss;
		if (!$this->system404 && $controllerMiss) {
			$this->system404 = true;
			$this->controllerName = $controllerMiss;
			$this->dispatching();
		} else 
			throw new Exception($this->exception, 404);
	}
	
	/**
	 * 分派消息
	 */
	public function dispatching()
	{
		$this->_checkController();
		$controller = App::singleton($this->controllerClass, array($this->controllerName));
		$controller->runAction($this->actionName);
	}
	
	/**
	 * 检测文件和类存在情况
	 */
	private function _checkController()
	{
		if (empty($this->controllerName)) 
			$this->controllerName = App::instance()->controllerDefault;
			
		$controllerName = ucfirst($this->controllerName);
		
		///
		$file = $controllerName.'.php';
		App::import($file, $this->controllerDir, false) or 
			$this->goto404("控制器文件({$file})不存在。");
		
		///
		$this->controllerClass = 'controller'.$controllerName;
		class_exists($this->controllerClass) or 
			$this->goto404("控制器类({$this->controllerClass})不存在。");
	}
}
